<script setup>
import ChartItem from "../components/chart/testBackChartItem.vue";
</script>
<template lang="">
    <div class="container" v-loading="loading">
        <el-container class="el-container">
            <el-header :height="100" class="custom-header">
                <el-row class="header-row">
                    <div>回测</div>
                    <el-button size="small" @click="openPanelEvent()" type="primary" >控制面板</el-button>
                </el-row>
            </el-header>
            <el-main class="el-main">
                <div class="grids">
                    <div class="grids_item" v-for="i in 4" :key="i">
                        <ChartItem :id="'chart_main_' + i" :goodList="goodList" :rate="rate" :union="true" :currentSize="currentSize"></ChartItem>
                    </div>
                </div>
            </el-main>
        </el-container>
        <el-dialog v-model="openPanel" title="控制面板" draggable overflow width="80%">
          <div >
            <el-container>
              <el-header height="90px">
                <el-row :gutter="20">
                  <el-col :span="4">
                    <el-container>
                      <el-header height="20px">总值</el-header>
                      <el-main  height="60px" class="money">￥{{resultSummary ? resultSummary.TotalDeposit : '----'}}</el-main>
                    </el-container>   
                  </el-col>
                  <el-col :span="4">
                    <el-container>
                      <el-header height="20px">本金</el-header>
                      <!-- <el-main  height="60px" class="money">￥{{goodList.find(v => v.goodsTraderId == form.goodsTraderId).initialCash}}</el-main> -->
                      <el-main  height="60px" class="money">￥{{resultSummary ? resultSummary.initialCash : '----'}}</el-main>
                    </el-container>
                  </el-col>
                  <el-col :span="4">
                    <el-container>
                      <el-header height="20px">盈亏</el-header>
                      <el-main  height="60px" class="money">￥{{resultSummary ? resultSummary.FloatingPL : '----'}}</el-main>
                    </el-container>
                  </el-col>
                  <el-col :span="4">
                    <el-container>
                      <el-header height="20px">手续费</el-header>
                      <el-main  height="60px" class="money">￥{{resultSummary ? resultSummary.commission : '----'}}</el-main>
                    </el-container>
                  </el-col>
                  <el-col :span="4">
                    <el-container>
                      <el-header height="20px">可用资金</el-header>
                      <el-main  height="60px" class="money">￥{{resultSummary ? resultSummary.FreeMargin : '----'}}</el-main>
                    </el-container>
                  </el-col>
                </el-row>
              </el-header>
              <el-container>
                <el-aside width="300px">
                  <el-form :model="form" label-width="auto" style="max-width: 1000px">
                    <el-form-item label="品种">
                      <el-select filterable v-model="form.goodsTraderId" placeholder="" style="width: 220px">
                        <el-option v-for="{text,goodsTraderId} in goodList" :key="goodsTraderId" :label="text" :value="goodsTraderId">
                        </el-option>
                      </el-select>
                    </el-form-item>
                    <el-form-item label="方向" >
                      <el-radio-group v-model="form.position">
                        <el-radio  v-for="{text,position} in positions" :key="position" :value="position" size="large">{{text}}</el-radio>
                      </el-radio-group>
                    </el-form-item>
                    <el-form-item label="手数">
                      <el-input-number
                        v-model="form.size"
                        style="width: 220px"
                        :min="0.01"
                        :precision="2"
                        :step="0.01"
                        controls-position="right"
                      />
                    </el-form-item>
                    <el-form-item label="止盈">
                      <el-input-number
                        v-model="form.takeProfit"
                        style="width: 220px"
                        :min="0.00"
                        :precision="2"
                        :step="0.01"
                        controls-position="right"
                      />
                    </el-form-item>
                    <el-form-item label="止损">
                      <el-input-number
                        v-model="form.stopLoss"
                        style="width: 220px"
                        :min="0.00"
                        :precision="2"
                        :step="0.01"
                        controls-position="right"
                      />
                    </el-form-item>
                    <el-form-item label="价格">
                      <el-input-number
                        v-model="form.price"
                        style="width: 220px"
                        :min="0.01"
                        :precision="2"
                        :step="0.01"
                        controls-position="right"
                        :disabled="form.operate == 'marketOrder'"
                      />
                    </el-form-item>
                    <el-form-item label="类型">
                      <el-select filterable v-model="form.type" placeholder="" style="width: 220px" :disabled="form.operate == 'marketOrder'">
                        <el-option v-for="{text,type} in types" :key="type" :label="text" :value="type">
                        </el-option>
                      </el-select>
                    </el-form-item>
                    <el-form-item label="有效期">
                      <el-date-picker
                        v-model="form.valid"
                        type="datetime"
                        value-format="YYYY-MM-DD HH:mm:ss"
                        :disabled="form.operate == 'marketOrder'"
                      />
                    </el-form-item>
                    <el-form-item label="操作">
                      <el-select filterable v-model="form.operate" placeholder="" style="width: 220px">
                        <el-option v-for="{text,operate} in operates" :key="operate" :label="text" :value="operate">
                        </el-option>
                      </el-select>
                    </el-form-item>
                  </el-form>
                  <el-row>
                    <el-col :span="16"><el-button type="danger" style="width:90%;" :disabled="currentSize >= goodList.find(v => v.goodsTraderId == form.goodsTraderId).lineInfo.lineList.length" @click="order()">下单</el-button></el-col>
                    <el-col :span="8"><el-button type="warning" style="width:80%;" @click="resetForm">重置</el-button></el-col>
                  </el-row>                
                </el-aside>
                <el-main>
                  <el-table v-if="resultTableList" :data="resultTableList" border style="width:100%;height:490px;">
                    <el-table-column prop="ticksId" label="订单号" width="85" />
                    <el-table-column prop="traderGoods" label="交易品种" width="140" />
                    <el-table-column prop="position" label="方向" />
                    <el-table-column prop="size" label="手数" />
                    <el-table-column prop="price" label="价格" />
                    <el-table-column prop="tradeDateTime" label="时间" width="170" />
                    <el-table-column prop="takeProfit" label="止盈" />
                    <el-table-column prop="stopLoss" label="止损" />
                    <el-table-column prop="status" label="成交状态" />
                  </el-table>
                <el-table v-else :data="tableList" border style="width:100%;height:490px;">
                    <el-table-column prop="ticksId" label="订单号" width="85" />
                    <el-table-column prop="goods" label="交易品种" width="140" />
                    <el-table-column prop="position" label="方向" />
                    <el-table-column prop="size" label="手数" />
                    <el-table-column prop="price" label="价格" />
                    <el-table-column prop="lineTime" label="时间" width="170" />
                    <el-table-column prop="takeProfit" label="止盈" />
                    <el-table-column prop="stopLoss" label="止损" />
                    <el-table-column align="center" width="220">
                      <template #header>
                        功能
                      </template>
                      <template #default="scope">
                        <el-button size="small" @click="sellOrder(scope.$index, scope.row)" type="warning" :disabled="!!orderList.find(order => order.ticksId == scope.row.ticksId).sellLineId">{{orderList.find(order => order.ticksId == scope.row.ticksId).sellLineId?'已平仓':'平仓'}}</el-button>
                        <el-button size="small" @click="modifyOrder(scope.$index, scope.row)" type="danger">修改</el-button>
                        <el-button size="small" @click="removeOrder(scope.$index, scope.row)" type="danger">删除</el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </el-main>
              </el-container>
              <el-footer>
                <div class="foot">
                    <el-row>
                      <el-col :span="8"></el-col>
                      <el-col :span="8">
                        <div class="control">
                          <span v-html="controlSvgList.leftForward" class="icon" @click="resetTime()"></span>
                          <span v-html="controlSvgList.leftRate" class="icon"  @click="changeRate(-1)"></span>
                          <span v-html="!play?controlSvgList.play:controlSvgList.pause" class="icon" @click="switchPlay()"></span>
                          <span v-html="controlSvgList.rightRate" class="icon" @click="changeRate(1)"></span>
                          <span v-html="controlSvgList.rightForward" class="icon" @click="endTime()"></span>
                        </div>
                      </el-col>
                      <el-col :span="8" class="rate_text"> 当前速率 : {{rate}}</el-col>
                    </el-row>
                  </div>
              </el-footer>
            </el-container>
          </div>
        </el-dialog>
        <el-dialog v-model="openModify" width="250px" title="修改">
          <el-form :model="modifyInfo" label-width="auto">
            <el-form-item label="止盈">
              <el-input-number
                v-model="modifyInfo.takeProfit"
                style="width: 220px"
                :min="0.00"
                :precision="2"
                :step="0.01"
                controls-position="right"
              />
            </el-form-item>
            <el-form-item label="止损">
              <el-input-number
                v-model="modifyInfo.stopLoss"
                style="width: 220px"
                :min="0.00"
                :precision="2"
                :step="0.01"
                controls-position="right"
              />
            </el-form-item>
            <el-button  @click="modifyCommit()" type="danger" style="width:100%;">确认修改</el-button>
          </el-form>
        </el-dialog>
    </div>
</template>
<script>
import { mapState,mapActions } from 'pinia';
import { tradeId,goodsTradeArray,crosshair,charts,currentChartId,originCrosshair } from '../store.js'
import { getKlineFromTimezone,commitOrderList} from '../apis.js'
// import { nanoid } from 'nanoid'
import svg from '../assets/svgList.js'
import moment from "moment-timezone"

export default {
    data(){
        return{
            orderId: 1000,
            openModify:false,
            orderList:[],
            timeOutId:undefined,
            play:true,
            controlSvgList:undefined,
            tradeIdState:'',
            goodsTradeArrayState:[],
            rate:1,//速率
            openPanel:false,
            panelGoodsTraderId:undefined,
            loading:true,
            maxSize:undefined,
            currentSize:0,
            resultList:[], //返回的结果
            modifyInfo:{
              ticksId:undefined,
              takeProfit:0.00,
              stopLoss:0.00
            },
            positions:[
              {
                text:'多头',
                position:'long',
              },
              {
                text:'空头',
                position:'short',
              }
            ],
            types:[
              {
                text:'buy limit',
                type:'1',
              },
              {
                text:'sell limit',
                type:'2',
              },
              {
                text:'buy stop',
                type:'3',
              },
              {
                text:'sell stop',
                type:'4',
              }
            ],
            operates:[
              {
              text:'市价交易',
              operate:'marketOrder',
              },
              {
              text:'挂单交易',
              operate:'pendingOrder',
              },
            ],
            form:{
              goodsTraderId:null,
              position:'long',
              size:0.01,
              takeProfit:0.00,
              stopLoss:0.00,
              price:0.01,
              type:'1',
              valid:null,
              operate:'marketOrder',
            },
            rates:[0.1,0.3,0.5,0.8,1,2,3,4,5]
        }
    },
    watch:{
      crosshair(newVal){
        if(!newVal) return; 
        for(let i = 0; i < this.charts.length; i++){
          const chart = this.charts[i];
          if(chart.id != this.currentChartId){
            chart.getChartStore().getCrosshairStore().setFromData(newVal);
          }
        }
      },
      currentSize(newVal){
        let goodsTraderIdTotals = this.goodsTradeArrayState.map(goodsTrade => ({goodsTraderId:goodsTrade.goodsTraderId,totalSize:goodsTrade.lineInfo.totalSize}));
        //加载途中
        goodsTraderIdTotals.forEach(goodsTraderIdTotal => {
          let goodsTraderId = goodsTraderIdTotal.goodsTraderId;
          let totalSize = goodsTraderIdTotal.totalSize;
          if(newVal == totalSize && !this.resultList.find(r => r.goodsTraderId == goodsTraderId)){
            this.commit(goodsTraderId);
          }
        })
        if(newVal == this.maxSize){
          //结束了
          goodsTraderIdTotals.forEach(goodsTraderIdTotal => {
          let goodsTraderId = goodsTraderIdTotal.goodsTraderId;
          if(!this.resultList.find(r => r.goodsTraderId == goodsTraderId)){
            this.commit(goodsTraderId);
          }
        })
        }
      }
    },
    computed:{
        ...mapState(tradeId, ['tradeId']),
        ...mapState(goodsTradeArray, ['goodsTradeArray']),
        ...mapState(crosshair, ['crosshair']),
        ...mapState(charts, ['charts']),
        ...mapState(currentChartId, ['currentChartId']),
        goodList(){
            return this.goodsTradeArrayState.map(v => ({...v,text:`${v.goods} ${v.period} (${v.beginTime} - ${v.endTime}) ${v.initialCash}`}))
        },
        tableList(){
          return this.orderList.filter(order => order.goodsTraderId == this.form.goodsTraderId).map(order => (
            {
              goods:this.goodList.find(v => v.goodsTraderId == order.goodsTraderId).goods,
              ...order,
              position:this.positions.find(v => v.position == order.position).text,
              price:order.price?order.price:'市价交易',
            }
          ));
        },
        resultSummary(){
          let result = this.resultList.find(result => result && result.goodsTraderId == this.form.goodsTraderId);
          if(!!result){
            return result.summary;
          }
          else{
            return undefined;
          }
        },
        resultTableList(){
          let result = this.resultList.find(result => result && result.goodsTraderId == this.form.goodsTraderId);
          if(!!result){
            let list = result.openTrades;
            list = list.map(v => ({...v,status:'已成交'}));
            let list2 = result.FailTrades;
            list2 = list2.map(v => ({...v,status:'未成交'}));
            list = [...list,...list2];
            list = list.map(v => ({...v,position:v.position == 'short'?'空头':'多头'}));
            return list;
            // return result.openTrades;
            // return result.FailTrades;
          }
          else{
            return undefined;
          }
        },
        // availCash(){
        //   let initialCash =  this.goodList.find(v => v.goodsTraderId == form.goodsTraderId).initialCash;
        //   this.orderList.filter
        // },
        ...mapState(originCrosshair, ['originCrosshair']),
    },
    mounted(){
        this.tradeIdState = this.tradeId;
        this.goodsTradeArrayState = this.goodsTradeArray;
        this.getAllLineInfo(
          () => {
            this.maxSize = Math.max(...this.goodsTradeArrayState.map(v => v.lineInfo.lineList.length));
            this.lineStep();
          }
        );
        this.resetForm();
        this.controlSvgList = svg.controlSvgList;
    },
    methods:{
      ...mapActions(crosshair,{setCrosshair:'set'}),
      openPanelEvent(){
        this.openPanel = true;
        this.panelGoodsTraderId = undefined;
      },
      getAllLineInfo(fn){
        let size = this.goodsTradeArrayState.length;
        let completedSize = 0;
        let exec = async (goodInfo) => {
          let id = goodInfo.goodsTraderId;
          let data = await getKlineFromTimezone(goodInfo);
          this.goodsTradeArrayState.forEach(good => {
            if(good.goodsTraderId == id){
              good.lineInfo = {totalSize:data.lineList.length,...data};
            }
          });
          completedSize++;
          if(completedSize == size){
            this.loading = false;
            !!fn && fn();
          }
        }
        this.goodsTradeArrayState.forEach(goodInfo => {exec(goodInfo)});
      },
      lineStep(){
        let stepTime = parseInt(1 * 1000 / 3);
        stepTime = parseFloat(stepTime / this.rate);
        this.timeOutId = setTimeout(() =>{
          this.currentSize ++;
          if(this.currentSize == this.maxSize){
            this.currentSize = this.maxSize;
          }
          else{
            this.lineStep();
            let crosshair;
            try{
              if(this.originCrosshair){
                crosshair = this.charts.find(chart => chart.id == this.currentChartId).getChartStore().getCrosshairStore().getData(this.originCrosshair);
              }
              this.setCrosshair(crosshair);
            }
            catch(e){}
          }
        },stepTime);
      },
      resetForm(){
        this.form = {
          goodsTraderId:this.goodList[0].goodsTraderId,
          position:'long',
          size:0.01,
          takeProfit:0.00,
          stopLoss:0.00,
          price:0.01,
          type:'1',
          valid:null,
          operate:'marketOrder',
        }
      },
      changeRate(step){
        let currentStep = this.rates.indexOf(this.rate);
        currentStep += step;
        if(currentStep < 0 ){
          currentStep = 0;
        }
        else if(currentStep >= this.rates.length){
          currentStep = this.rates.length - 1;
        }
        this.rate = this.rates[currentStep];
        clearTimeout(this.timeOutId);
        if(this.play){
          this.lineStep();
        }
        else{}
      },
      switchPlay(){
        this.play=!this.play;
        if(this.play){
          //播放
          clearTimeout(this.timeOutId);
          this.lineStep();
        }
        else{
          //暂停
          clearTimeout(this.timeOutId);
        }
      },
      resetTime(){
        this.currentSize = 0;
        // if(this.play){
        //   //播放中
        //   clearTimeout(this.timeOutId);
        //   this.lineStep();
        // }
        // else{
        //   //暂停中
        //   clearTimeout(this.timeOutId);
        // }
        this.play = true;
        this.orderList = [];
        this.resultList = [];
        clearTimeout(this.timeOutId);
        this.lineStep();
      },
      endTime(){
        this.currentSize = this.maxSize;
        clearTimeout(this.timeOutId);
      },
      order(){
        try{
          // let ticksId = nanoid(); //订单id
          this.orderId++;
          let ticksId = this.orderId; //订单id
          let klineId = this.goodList.find(v => v.goodsTraderId == this.form.goodsTraderId).lineInfo.lineList[this.currentSize - 1].pkId;
          let lineTime = this.goodList.find(v => v.goodsTraderId == this.form.goodsTraderId).lineInfo.lineList[this.currentSize - 1].timestamp;
          let timezone = this.goodList.find(v => v.goodsTraderId == this.form.goodsTraderId).lineInfo.timezone;
          lineTime = moment.tz(lineTime,timezone).format("YYYY-MM-DD HH:mm:ss");
          let order = {
            ticksId,
            klineId,
            ...this.form,
            // leverage:parseInt(this.form.leverage),
            lineTime
          };
          if(this.form.operate == 'marketOrder'){
            order = {...order,price:0,type:0,valid:null};
          }
          this.orderList.push(order);
        }
        catch(e){}
      },
      removeOrder(index,row){
        //row.ticksId
        this.orderList = this.orderList.filter(order => order.ticksId != row.ticksId);
      },
      sellOrder(index,row){
        this.orderList.forEach(order => {
          if(order.ticksId == row.ticksId){
            order.sellLineId = this.goodList.find(v => v.goodsTraderId == this.form.goodsTraderId).lineInfo.lineList[this.currentSize - 1].pkId;
          }
        })
      },
      modifyOrder(index,row){
        // modifyInfo:{
        //       takeProfit:0.01,
        //       stopLoss:0.01
        //     },
        this.modifyInfo = {
          ticksId:row.ticksId,
          takeProfit:row.takeProfit,
          stopLoss:row.stopLoss
        };
        this.openModify = true;
      },
      modifyCommit(){
        this.openModify = false;
        this.orderList.forEach(order => {
          if(order.ticksId == this.modifyInfo.ticksId){
            order.takeProfit = this.modifyInfo.takeProfit;
            order.stopLoss = this.modifyInfo.stopLoss;
          }
        })
      },
      async commit(goodsTraderId){
          let commitOpts = {
            tradeId:this.tradeIdState,
            goodsTradeArray:[]
            // goodsTradeArray:[
            //   {
            //     goodsTraderId:'',
            //     ticks:[],
            //   }
            // ]
          }
          // let goodsTraderIds = new Array(...(new Set(this.orderList.map(v => v.goodsTraderId))));
          let goodsTraderIds = [goodsTraderId];
          goodsTraderIds.forEach(goodsTraderId => {
            let goodsTrade = {
              goodsTraderId,
              ticks:[]
            }
            let orders = this.orderList.filter(order => order.goodsTraderId == goodsTraderId);
            orders.forEach(order => {
              goodsTrade.ticks.push({
                ...order,
                lineTime:undefined,
                sellLineId:undefined,
                orderType:'buy',
                goodsTraderId:undefined,
                ticksId:`${order.ticksId}`,
                type:parseInt(order.type)
              });
              if(order.sellLineId){
                goodsTrade.ticks.push({
                  ...order,
                  lineTime:undefined,
                  sellLineId:undefined,
                  klineId:order.sellLineId,
                  orderType:'sell',
                  goodsTraderId:undefined,
                  ticksId:`${order.ticksId}`,
                  type:parseInt(order.type)
                });
              }
            });
            commitOpts.goodsTradeArray.push(goodsTrade);
          })
          let result = await commitOrderList(commitOpts);
          result = result[0];
          if(!this.resultList.find(r => r && r.goodsTraderId == result.goodsTraderId)){
            this.resultList.push(result);
          }
      }
    }
}
</script>
<style scoped>
.container {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex-wrap: wrap;
  }
body {
    margin: 0;
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background-color: #f2f3f5;
  }
  
  div,
  p {
    box-sizing: border-box;
  }
  
  p {
    margin: 0;
  }
  
  .commit {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex-wrap: wrap;
  }
  .el-container{
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
  }
  .custom-header{
    padding: 10px 20px;
    padding-bottom: 0px;
  }
  .option_item{
    display: flex;
    width: 100%;
  }
  .option_text{
    flex-grow: 1;
  }
  .option_icon{
  
  }
  .option_icon_start_filled{
    padding: 0px 11px;
    line-height:100%;
    height:100%;
  }
  .option_icon_start{
    padding: 0px 15px;
    line-height:100%;
    height:100%;
  }
  .header-row{
    display: flex;
    justify-items: center;
    justify-self: center;
  }
  .header-row>*:nth-child(n+2){
    margin-left: 20px;
  }
  .grids{
    display: grid;
    /* grid-template-rows:50% 50%;
    grid-template-columns:50% 50%; */
    column-gap:0;
    /* 横向等比分割 */
    justify-content: space-evenly;
    /* 纵向等比分割 */
    align-content: space-evenly;
    grid-template-columns: repeat(2, 50%);
    grid-template-rows: repeat(2, 50%);
    width: 100%;
    height: 100%;
  }
  .grids_item{
    border-right: 1px solid rgba(212, 203, 203, 0.534);
    border-bottom: 1px solid rgba(212, 203, 203, 0.534);
  }
  .money{
    font-size: 26px;
    font-weight: 600;
  }
  .control{
    display: flex;
    justify-content:space-between;
    align-self: center;
    height: 100%;
    line-height: 1;
  }
  .control .icon{
    display: flex;
    justify-content: center;
    align-self: center;
    cursor: pointer;
  }
  .rate_text{
    display: flex;
    padding-left: 20px;
    align-self: center;
    height: 100%;
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+/Edge */
    user-select: none; /* 标准语法 */
  }
  .foot{
    padding-top: 20px;
    width: 100%;
    height: 100%;
  }
</style>